#pragma once

class Texture {
protected:

	GLuint texture;
	
public:
	
	void bind();
	
	void loadPNG(const char* fileName);
	
	Texture();
	
	~Texture();
	
};

void Texture::bind(){
	glBindTexture(GL_TEXTURE_2D,texture);
}
	
void Texture::loadPNG(const char* fileName){
	png_structp png_ptr = 0;
	png_infop info_ptr = 0;
	FILE* f = 0;
	try {
		f = fopen(fileName,"rb");
		if (!f)
			throw(std::string(fileName)+" not found");
		unsigned char header[8];
		if (fread(header,1,8,f)!=8)
			throw(std::string(fileName)+" read error");
		if (png_sig_cmp(header, 0, 8))
			throw(std::string(fileName)+" not PNG format");
		png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, 0, 0, 0);
		
		if (png_ptr) {
			info_ptr = png_create_info_struct(png_ptr);
			if (info_ptr) {
				if (!setjmp(png_jmpbuf(png_ptr))){
					png_uint_32 width, height;
					int bit_depth, color_type, interlace_type;						
					png_init_io(png_ptr, f);
					png_set_sig_bytes(png_ptr, 8); 
					png_read_info(png_ptr, info_ptr); 
					png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);
					// делаем все чтобы png читался как GL_RGBA
					if (color_type == PNG_COLOR_TYPE_PALETTE)
						png_set_palette_to_rgb(png_ptr);
					if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8)
						png_set_expand_gray_1_2_4_to_8(png_ptr);
					if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
						png_set_tRNS_to_alpha(png_ptr);
					if (bit_depth == 16)
					#if PNG_LIBPNG_VER >= 10504
						png_set_scale_16(png_ptr);
					#else
						png_set_strip_16(png_ptr);
					#endif
					png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
					png_set_interlace_handling(png_ptr);
					png_read_update_info(png_ptr, info_ptr);
					if (color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
       					png_set_gray_to_rgb(png_ptr);				
					// читаем пнг построчно		
					glBindTexture(GL_TEXTURE_2D,texture);		
					glTexImage2D(GL_TEXTURE_2D,0,GL_RGBA,width,height,0,GL_RGBA,GL_UNSIGNED_BYTE,0);
					png_byte* buffer = new png_byte[width*4];
					// узнаем сколько надо проходов для interlace картинки
					int number_of_passes = png_set_interlace_handling(png_ptr);
				    for (int i = 0; i<number_of_passes; i++)
						for (unsigned int y=0; y<height; y++){
							png_read_row(png_ptr, buffer, NULL);						
							glTexSubImage2D(GL_TEXTURE_2D,0,0,height-y-1,width,1,GL_RGBA,GL_UNSIGNED_BYTE,buffer);
						}
					delete[] buffer;								
				}
			}
			png_destroy_read_struct(&png_ptr, &info_ptr, 0);
		}
		
		
		fclose(f);
	} 
	catch (const std::string &errorString){
		png_destroy_read_struct(&png_ptr, &info_ptr, 0);
		if (f) 
			fclose(f);
		printf("error : %s\n",errorString.c_str());
		exit(1);
	}
}

Texture::Texture(){
	glGenTextures(1,&texture);
	glBindTexture(GL_TEXTURE_2D,texture);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
}
	
Texture::~Texture(){
	glDeleteTextures(1,&texture);
}

